package com.hanlp.utils;

import java.io.IOException;
import java.util.HashMap;
import java.util.Map;

/**
 * 东方财富可转债数据爬取工具类
 * 提供可转债行情、K线、基本信息等数据获取功能
 */
public class EastMoneyBondUtil {

    // 基础URL常量
    private static final String BASE_URL = "http://push2.eastmoney.com";
    private static final String HISTORY_URL = "http://push2his.eastmoney.com";
    private static final String DATACENTER_URL = "http://datacenter-web.eastmoney.com";

    // 默认token
    private static final String DEFAULT_UT = "bd1d9ddb04089700cf9c27f6f7426281";
    private static final String KLINE_UT = "fa5fd1943c7b386f172d6893dbfba10b";

    // 可转债相关字段
    private static final String BOND_FIELDS = "f43,f44,f45,f46,f60,f47,f48,f169,f170,f57,f58,f161,f162,f163";
    private static final String BOND_LIST_FIELDS = "f1,f2,f3,f4,f5,f6,f7,f8,f9,f10,f12,f13,f14,f15,f16,f17,f18,f20,f21,f23,f24,f25,f22,f11,f62,f128,f136,f115,f152";
    private static final String KLINE_FIELDS1 = "f1,f2,f3,f4,f5";
    private static final String KLINE_FIELDS2 = "f51,f52,f53,f54,f55,f56,f57,f58,f59,f60,f61";

    /**
     * 获取可转债列表
     *
     * @param pageNum   页码（从1开始）
     * @param pageSize  每页数量
     * @param sortField 排序字段（如：f3表示涨跌幅）
     * @param sortOrder 排序方式（1为正序，0为倒序）
     * @return JSON格式的可转债列表数据
     * @throws IOException 网络请求异常
     */
    public static String getConvertibleBondList(int pageNum, int pageSize, String sortField, int sortOrder) throws IOException {
        Map<String, String> params = new HashMap<>();
        params.put("pn", String.valueOf(pageNum));
        params.put("pz", String.valueOf(pageSize));
        params.put("po", String.valueOf(sortOrder));
        params.put("np", "1");
        params.put("ut", DEFAULT_UT);
        params.put("fltt", "2");
        params.put("invt", "2");
        params.put("fid", sortField);
        params.put("fs", "m:0+t:7"); // 可转债筛选条件
        params.put("fields", BOND_LIST_FIELDS);

        String url = HttpUtil.buildUrl(BASE_URL + "/api/qt/clist/get", params);
        return HttpUtil.get(url);
    }

    /**
     * 获取可转债列表Bean对象
     * @param pageNum 页码（从1开始）
     * @param pageSize 每页数量
     * @param sortField 排序字段（如：f3表示涨跌幅）
     * @param sortOrder 排序方式（1为正序，0为倒序）
     * @return ApiResponse<List < ConvertibleBondData>>对象
     * @throws IOException 网络请求异常
     */
    /*
    public static ApiResponse<List<ConvertibleBondData>> getConvertibleBondListBean(int pageNum, int pageSize, String sortField, int sortOrder) throws IOException {
        String jsonResponse = getConvertibleBondList(pageNum, pageSize, sortField, sortOrder);
        return JsonUtil.parseConvertibleBondList(jsonResponse);
    }
    */

    /**
     * 获取可转债列表（默认按涨跌幅倒序）
     *
     * @param pageNum  页码
     * @param pageSize 每页数量
     * @return JSON格式的可转债列表数据
     * @throws IOException 网络请求异常
     */
    public static String getConvertibleBondList(int pageNum, int pageSize) throws IOException {
        return getConvertibleBondList(pageNum, pageSize, "f3", 0);
    }

    /**
     * 获取可转债实时行情数据
     *
     * @param secid 可转债代码，格式：市场代码.可转债代码（如：0.123456）
     * @return JSON格式的可转债行情数据
     * @throws IOException 网络请求异常
     */
    public static String getConvertibleBondRealTime(String secid) throws IOException {
        Map<String, String> params = new HashMap<>();
        params.put("secid", secid);
        params.put("fields", BOND_FIELDS);

        String url = HttpUtil.buildUrl(BASE_URL + "/api/qt/stock/get", params);
        return HttpUtil.get(url);
    }

    /**
     * 获取可转债实时行情数据Bean对象
     * @param secid 可转债代码，格式：市场代码.可转债代码（如：0.123456）
     * @return ConvertibleBondData对象
     * @throws IOException 网络请求异常
     */
    /*
    public static ConvertibleBondData getConvertibleBondRealTimeBean(String secid) throws IOException {
        String jsonResponse = getConvertibleBondRealTime(secid);
        // 注意：这里需要单独解析单个可转债数据，可以复用JsonUtil中的解析逻辑
        return JsonUtil.parseStockRealTimeData(jsonResponse) != null ? 
            convertStockDataToBondData(JsonUtil.parseStockRealTimeData(jsonResponse), secid) : null;
    }
    */

    // 辅助方法：将股票数据转换为可转债数据
    /*
    private static ConvertibleBondData convertStockDataToBondData(StockRealTimeData stockData, String secid) {
        if (stockData == null) return null;
        
        ConvertibleBondData bondData = new ConvertibleBondData();
        bondData.setLatestPrice(stockData.getLatestPrice());
        bondData.setChangePercent(stockData.getChangePercent());
        bondData.setChangeAmount(stockData.getChangeAmount());
        bondData.setVolume(stockData.getVolume());
        bondData.setTurnover(stockData.getTurnover());
        bondData.setBondCode(stockData.getStockCode());
        bondData.setBondName(stockData.getStockName());
        bondData.setOpenPrice(stockData.getOpenPrice());
        bondData.setHighPrice(stockData.getHighPrice());
        bondData.setLowPrice(stockData.getLowPrice());
        bondData.setClosePrice(stockData.getClosePrice());
        return bondData;
    }
    */

    /**
     * 获取可转债实时行情数据（自定义字段）
     *
     * @param secid  可转债代码
     * @param fields 自定义字段，用逗号分隔
     * @return JSON格式的可转债行情数据
     * @throws IOException 网络请求异常
     */
    public static String getConvertibleBondRealTime(String secid, String fields) throws IOException {
        Map<String, String> params = new HashMap<>();
        params.put("secid", secid);
        params.put("fields", fields);

        String url = HttpUtil.buildUrl(BASE_URL + "/api/qt/stock/get", params);
        return HttpUtil.get(url);
    }

    /**
     * 获取可转债K线数据
     *
     * @param secid      可转债代码
     * @param klineType  K线类型（1:1分钟, 5:5分钟, 15:15分钟, 30:30分钟, 60:60分钟, 101:日K, 102:周K, 103:月K）
     * @param adjustType 复权类型（0:不复权, 1:前复权, 2:后复权）
     * @param startDate  开始日期（格式：20220101）
     * @param endDate    结束日期（格式：20221231）
     * @return JSON格式的K线数据
     * @throws IOException 网络请求异常
     */
    public static String getConvertibleBondKLine(String secid, int klineType, int adjustType,
                                                 String startDate, String endDate) throws IOException {
        Map<String, String> params = new HashMap<>();
        params.put("secid", secid);
        params.put("ut", KLINE_UT);
        params.put("fields1", KLINE_FIELDS1);
        params.put("fields2", KLINE_FIELDS2);
        params.put("klt", String.valueOf(klineType));
        params.put("fqt", String.valueOf(adjustType));
        params.put("beg", startDate);
        params.put("end", endDate);

        String url = HttpUtil.buildUrl(HISTORY_URL + "/api/qt/stock/kline/get", params);
        return HttpUtil.get(url);
    }

    /**
     * 获取可转债K线数据Bean对象
     * @param secid 可转债代码
     * @param klineType K线类型（1:1分钟, 5:5分钟, 15:15分钟, 30:30分钟, 60:60分钟, 101:日K, 102:周K, 103:月K）
     * @param adjustType 复权类型（0:不复权, 1:前复权, 2:后复权）
     * @param startDate 开始日期（格式：20220101）
     * @param endDate 结束日期（格式：20221231）
     * @return KLineData对象
     * @throws IOException 网络请求异常
     */
    /*
    public static KLineData getConvertibleBondKLineBean(String secid, int klineType, int adjustType, 
                                                       String startDate, String endDate) throws IOException {
        String jsonResponse = getConvertibleBondKLine(secid, klineType, adjustType, startDate, endDate);
        return JsonUtil.parseKLineData(jsonResponse);
    }
    */

    /**
     * 获取可转债基本信息
     *
     * @param bondCode 可转债代码（不带市场前缀）
     * @return JSON格式的可转债基本信息
     * @throws IOException 网络请求异常
     */
    public static String getConvertibleBondInfo(String bondCode) throws IOException {
        Map<String, String> params = new HashMap<>();
        params.put("reportName", "RPT_BOND_CB_LIST");
        params.put("columns", "SECURITY_CODE,SECURITY_NAME_ABBR,CONVERT_STOCK_CODE,CONVERT_STOCK_NAME,CONVERT_PRICE,CONVERT_VALUE,PREMIUM_RT,RATING,REMAIN_YEAR,YTM_RT,PURE_BOND_VALUE,PURE_BOND_PREMIUM_RT");
        params.put("quoteColumns", "f2~01~CONVERT_STOCK_CODE~CONVERT_STOCK_PRICE,f3~01~CONVERT_STOCK_CODE~CONVERT_STOCK_CHG_PCT");
        params.put("filter", "(SECURITY_CODE=\"" + bondCode + "\")");
        params.put("pageNumber", "1");
        params.put("pageSize", "1");

        String url = HttpUtil.buildUrl(DATACENTER_URL + "/api/data/v1/get", params);
        return HttpUtil.get(url);
    }

    /**
     * 获取所有可转债基本信息列表
     *
     * @param pageNum    页码
     * @param pageSize   每页数量
     * @param sortColumn 排序字段（如：CONVERT_PRICE）
     * @param sortType   排序类型（-1:倒序, 1:正序）
     * @return JSON格式的可转债基本信息列表
     * @throws IOException 网络请求异常
     */
    public static String getAllConvertibleBondInfo(int pageNum, int pageSize, String sortColumn, int sortType) throws IOException {
        Map<String, String> params = new HashMap<>();
        params.put("reportName", "RPT_BOND_CB_LIST");
        params.put("columns", "SECURITY_CODE,SECURITY_NAME_ABBR,CONVERT_STOCK_CODE");
        params.put("quoteColumns", "f2~01~CONVERT_STOCK_CODE~CONVERT_STOCK_PRICE,f3~01~CONVERT_STOCK_CODE~CONVERT_STOCK_CHG_PCT");
        params.put("pageNumber", String.valueOf(pageNum));
        params.put("pageSize", String.valueOf(pageSize));

        if (sortColumn != null && !sortColumn.isEmpty()) {
            params.put("sortColumns", sortColumn);
            params.put("sortTypes", String.valueOf(sortType));
        }

        String url = HttpUtil.buildUrl(DATACENTER_URL + "/api/data/v1/get", params);
        return HttpUtil.get(url);
    }

    /**
     * 获取可转债赎回数据
     *
     * @param bondCode 可转债代码（可选，为空则获取所有）
     * @param pageNum  页码
     * @param pageSize 每页数量
     * @return JSON格式的可转债赎回数据
     * @throws IOException 网络请求异常
     */
    public static String getConvertibleBondRedeemData(String bondCode, int pageNum, int pageSize) throws IOException {
        Map<String, String> params = new HashMap<>();
        params.put("reportName", "RPT_BOND_CB_REDEEM");
        params.put("columns", "SECURITY_CODE,SECURITY_NAME_ABBR,REDEEM_PRICE,REDEEM_START_DATE,REDEEM_END_DATE,REDEEM_CONDITION");

        if (bondCode != null && !bondCode.isEmpty()) {
            params.put("filter", "(SECURITY_CODE=\"" + bondCode + "\")");
        }

        params.put("pageNumber", String.valueOf(pageNum));
        params.put("pageSize", String.valueOf(pageSize));

        String url = HttpUtil.buildUrl(DATACENTER_URL + "/api/data/v1/get", params);
        return HttpUtil.get(url);
    }

    /**
     * 根据转股溢价率筛选可转债
     *
     * @param minPremium 最小溢价率（%）
     * @param maxPremium 最大溢价率（%）
     * @param pageNum    页码
     * @param pageSize   每页数量
     * @return JSON格式的筛选结果
     * @throws IOException 网络请求异常
     */
    public static String getConvertibleBondByPremium(double minPremium, double maxPremium,
                                                     int pageNum, int pageSize) throws IOException {
        Map<String, String> params = new HashMap<>();
        params.put("reportName", "RPT_BOND_CB_LIST");
        params.put("columns", "SECURITY_CODE,SECURITY_NAME_ABBR,CONVERT_STOCK_CODE");
        params.put("quoteColumns", "f2~01~CONVERT_STOCK_CODE~CONVERT_STOCK_PRICE,f3~01~CONVERT_STOCK_CODE~CONVERT_STOCK_CHG_PCT");
        params.put("filter", "(PREMIUM_RT>=" + minPremium + " and PREMIUM_RT<=" + maxPremium + ")");
        params.put("pageNumber", String.valueOf(pageNum));
        params.put("pageSize", String.valueOf(pageSize));
        params.put("sortColumns", "PREMIUM_RT");
        params.put("sortTypes", "1"); // 按溢价率正序排列

        String url = HttpUtil.buildUrl(DATACENTER_URL + "/api/data/v1/get", params);
        return HttpUtil.get(url);
    }

    /**
     * 根据剩余年限筛选可转债
     *
     * @param minYear  最小剩余年限
     * @param maxYear  最大剩余年限
     * @param pageNum  页码
     * @param pageSize 每页数量
     * @return JSON格式的筛选结果
     * @throws IOException 网络请求异常
     */
    public static String getConvertibleBondByRemainYear(double minYear, double maxYear,
                                                        int pageNum, int pageSize) throws IOException {
        Map<String, String> params = new HashMap<>();
        params.put("reportName", "RPT_BOND_CB_LIST");
        params.put("columns", "SECURITY_CODE,SECURITY_NAME_ABBR,CONVERT_STOCK_CODE");
        params.put("quoteColumns", "f2~01~CONVERT_STOCK_CODE~CONVERT_STOCK_PRICE,f3~01~CONVERT_STOCK_CODE~CONVERT_STOCK_CHG_PCT");
        params.put("pageNumber", String.valueOf(pageNum));
        params.put("pageSize", String.valueOf(pageSize));
        params.put("sortColumns", "SECURITY_CODE");
        params.put("sortTypes", "1"); // 按代码正序排列

        String url = HttpUtil.buildUrl(DATACENTER_URL + "/api/data/v1/get", params);
        return HttpUtil.get(url);
    }

    /**
     * 批量获取可转债实时行情（控制请求频率）
     *
     * @param secids  可转债代码数组
     * @param delayMs 每次请求间隔毫秒数
     * @return 可转债行情数据数组
     */
    public static String[] batchGetConvertibleBondData(String[] secids, long delayMs) {
        String[] results = new String[secids.length];

        for (int i = 0; i < secids.length; i++) {
            try {
                results[i] = getConvertibleBondRealTime(secids[i]);

                // 控制请求频率，避免被限制
                if (i < secids.length - 1 && delayMs > 0) {
                    HttpUtil.sleep(delayMs);
                }
            } catch (IOException e) {
                results[i] = "{\"error\":\"" + e.getMessage() + "\"}";
            }
        }

        return results;
    }

    /**
     * K线类型枚举
     */
    public static class KLineType {
        public static final int MIN_1 = 1;     // 1分钟
        public static final int MIN_5 = 5;     // 5分钟
        public static final int MIN_15 = 15;   // 15分钟
        public static final int MIN_30 = 30;   // 30分钟
        public static final int MIN_60 = 60;   // 60分钟
        public static final int DAILY = 101;   // 日K
        public static final int WEEKLY = 102;  // 周K
        public static final int MONTHLY = 103; // 月K
    }

    /**
     * 复权类型枚举
     */
    public static class AdjustType {
        public static final int NONE = 0;      // 不复权
        public static final int FORWARD = 1;   // 前复权
        public static final int BACKWARD = 2;  // 后复权
    }
}